package gemini.castor.ui.client.page.content.home.apply.personalinfo;

import gemini.castor.ui.client.constants.I18nConstants;
import gemini.castor.ui.client.page.widget.ErrorWidget;
import gemini.castor.ui.client.page.widget.TextFieldTextNumber;
import gemini.castor.ui.client.page.widget.address.AddressWidget;
import gemini.castor.ui.client.page.widget.identify.IdentifyWidget;
import gemini.castor.ui.client.page.widget.personalinfo.PersonalInfoWidget;
import gemini.castor.ui.client.page.widget.phone.PhoneWidget;
import gemini.castor.ui.client.utils.GuiUtils;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.validation.client.InvalidConstraint;
import com.google.gwt.validation.client.interfaces.IValidator;

public class PersonalInfoFormView extends Composite implements
		PersonalInfoFormPresenter.Display {

	@UiTemplate("PersonalInfoFormView.ui.xml")
	interface MyUiBinder extends UiBinder<Panel, PersonalInfoFormView> {
	}

	private static final MyUiBinder binder = GWT.create(MyUiBinder.class);

	private IValidator<PersonalInfoFormObject> validator;
	private PersonalInfoFormObject object;
	
	@Override
	public PersonalInfoFormObject getObject() {
		return object;
	}

	private I18nConstants constants;

	public PersonalInfoFormView() {
		initWidget(binder.createAndBindUi(this));
		validator = GWT.create(PersonalInfoFormObject.class);
		constants = GWT.create(I18nConstants.class);
	}
	
	@UiField
	CheckBox chxHasPersonalId;
	
	@UiHandler("chxHasPersonalId")
	void onCheckHasPersonalId(ValueChangeEvent<Boolean> e) {
		pnlPersonalId.setVisible(chxHasPersonalId.getValue());
		pnlPersonalInfo.setVisible(!chxHasPersonalId.getValue());
	}

	@UiField
	TextFieldTextNumber tbxPersonalId;
	
	@UiField
	HTMLPanel pnlPersonalId;
	
	@UiField
	HTMLPanel pnlPersonalInfo;

	@UiField
	ErrorWidget cnwError;

	@UiField
	PersonalInfoWidget pwgPersonalInfo;
	
	@UiField
	PersonalInfoWidget pwgSpousePersonalInfo;

	@UiField
	ListBox lbxLanguage;
	
	@UiField
	AddressWidget awgAddress;

	@UiField
	AddressWidget awgContactAddress;

	@UiField
	TextBox tbxFaxNumber;

	@UiField
	TextBox tbxEmail;

	@UiField
	IdentifyWidget iwgIdentify;

	@UiField
	PhoneWidget pwgPhone;

	@UiField
	CheckBox chxWithHoney;
	
	@UiField
	SimplePanel pnlCaptcha;
	
	private Image imgCaptcha;
	private int counter = 0;
	
	@Override
	public void loadCaptchaImage(){
		tbxCodeShown.setValue("");
		
		counter++;
		imgCaptcha = new Image("/SimpleCaptcha.jpg?counter="+counter);
		pnlCaptcha.clear();
		pnlCaptcha.add(imgCaptcha);
	}
	
	@UiHandler("chxWithHoney")
	void onCheckWithHoney(ValueChangeEvent<Boolean> e) {
		object.setWithHoney(chxWithHoney.getValue());
		pnlWithHoney.setVisible(chxWithHoney.getValue());
	}

	@UiField
	HTMLPanel pnlWithHoney;

	@UiField
	IdentifyWidget iwgHoneyIdentify;

	@UiField
	TextBox tbxCodeShown;

	@UiField
	RadioButton rdbAsAbove;

	@UiField
	RadioButton rdbOther;

	@UiHandler({ "rdbAsAbove", "rdbOther" })
	void onChangeContactAddress(ValueChangeEvent<Boolean> e) {
		object.setHasOtherContactAddress(rdbOther.getValue());
		awgContactAddress.setVisible(rdbOther.getValue());
	}

	@UiField
	Button btnSubmit;

	@UiField
	Button btnReset;

	@UiField
	Button btnTryNew;
	
	@UiHandler("btnTryNew")
	void onTryNew(ClickEvent e) {
		loadCaptchaImage();
	}

	@UiHandler("btnReset")
	void onReset(ClickEvent e) {
		reset();
	}

	@Override
	public Widget asWidget() {
		return this;
	}

	@Override
	public HasClickHandlers getPersionalSubmitClickHandlers() {
		return btnSubmit;
	}

	@Override
	public void loadData() {
		object = new PersonalInfoFormObject();
		
		pwgPersonalInfo.setObject(object.getPersonalInfo());
		pwgSpousePersonalInfo.setObject(object.getSpousePersonalInfo());

		iwgIdentify.setIdentifyObject(object.getIdentify());
		iwgHoneyIdentify.setIdentifyObject(object.getHoneyIdentify());

		pwgPhone.setPhoneObject(object.getPhone());

		awgAddress.setAddressObject(object.getAddress());
		awgContactAddress.setAddressObject(object.getContactAddress());

		Map<String,String> map = GuiUtils.getValueFromConstant(constants.stringLanguage());
		for (String key : map.keySet()) {
			lbxLanguage.addItem(map.get(key),key);
		}
		rdbAsAbove.addStyleDependentName("checked");
		
		loadCaptchaImage();

		cnwError.setMessage(constants.emptyField());
		reset();
	}
	
	@Override
	public boolean isValidate() {
		boolean result;
		if(chxHasPersonalId.getValue()){
			result = isPersonalIdValid();
		}else {
			result = isPersonalFormValid();
		}
		return result;
	}
	
	private boolean isPersonalIdValid() {
		resetStyle();
		bind();
		boolean result = true;
		if (object.getPersonalInfoId().isEmpty()) {
			tbxPersonalId.addStyleDependentName("error");
			cnwError.setVisible(true);
		}
		return result;
	}

	private boolean isPersonalFormValid() {
		resetStyle();
		bind();
		boolean mainValid = true;
		Set<InvalidConstraint<PersonalInfoFormObject>> invalidConstraints = validator
				.validate(object);
		Iterator<InvalidConstraint<PersonalInfoFormObject>> it = invalidConstraints
				.iterator();

		while (it.hasNext()) {
			if (mainValid) {
				mainValid = false;
			}
			InvalidConstraint<PersonalInfoFormObject> ic = it.next();
			showError(ic.getItemName(), ic.getMessage());
		}

		boolean mainInfoValid = pwgPersonalInfo.isValidate();

		boolean identifyValid = iwgIdentify.isValidate();

		boolean addressValid = awgAddress.isValidate();

		boolean phoneValid = pwgPhone.isValidate();

		boolean contactAddressValid = true;
		if (object.isHasOtherContactAddress()) {
			contactAddressValid = awgContactAddress.isValidate();
		}

		boolean spouseIdentifyValid = true;
		boolean spouseInfoValid = true;
		if (object.isWithSpouse()) {
			spouseInfoValid = pwgSpousePersonalInfo.isValidate();
			spouseIdentifyValid = iwgHoneyIdentify.isValidate();
		}
		
		boolean result = mainInfoValid && mainValid && identifyValid && spouseIdentifyValid
				&& contactAddressValid && addressValid && phoneValid
				&& spouseInfoValid;
		
		if(!result){
			cnwError.setVisible(true);
		} else {
			cnwError.setVisible(false);
		}
		
		return result;
	}

	private void showError(String widgetName, String errorString) {
		if (widgetName.equals("email")) {
			tbxEmail.addStyleDependentName("error");
		}
	}
	
	private void bind() {
		if(chxHasPersonalId.getValue()){
			bindId();
		} else {
			bindForm();
		}
	}
	
	private void bindId() {
		object.setPersonalInfoId(tbxPersonalId.getValue());
	}
	
	private void bindForm() {
		object.setPersonalInfoId("");
		object.setEmail(tbxEmail.getValue());
		object.setFaxNumber(tbxFaxNumber.getValue());
		object.setLanguage(lbxLanguage.getValue(lbxLanguage.getSelectedIndex()));
	}

	public void reset() {
		resetValue();
		resetStyle();
	}
	
	private void resetValue(){
		if(chxHasPersonalId.getValue()){
			resetValuePersonalId();
		} else {
			resetValueForm();
		}
		cnwError.setVisible(false);
	}
	
	private void resetValueForm(){
		tbxEmail.setValue("", true);
		tbxFaxNumber.setValue("", true);
		
		iwgIdentify.reset();
		iwgHoneyIdentify.reset();

		awgAddress.reset();
		awgContactAddress.reset();

		pwgPhone.reset();
		pwgPersonalInfo.reset();
		
		pwgSpousePersonalInfo.reset();
	}
	
	private void resetValuePersonalId(){
		tbxPersonalId.setValue("", true);
	}
	
	private void resetStyle(){
		if(chxHasPersonalId.getValue()){
			resetStylePersonalId();
		} else {
			resetStyleForm();
		}
	}
	
	private void resetStyleForm(){
		tbxEmail.removeStyleDependentName("error");
	}
	
	private void resetStylePersonalId(){
		tbxPersonalId.removeStyleDependentName("error");
	}

	@Override
	public String getCaptchaString() {
		return tbxCodeShown.getValue();
	}

	@Override
	public void errorFromServer(String messageCode) {
		 GuiUtils.alert(constants.getString(messageCode));
	}
}
